/*
 * Copyright (C) 2015 Michele Zanella <it.polimi.meteoCal>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package it.polimi.meteoCal.boundary;

import it.polimi.meteoCal.control.PasswordEncrypter;
import it.polimi.meteoCal.control.core.ResetManager;
import it.polimi.meteoCal.entity.Users;
import java.security.Principal;
import java.util.Calendar;
import java.util.Date;
import javax.ejb.EJB;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.validation.ConstraintViolationException;
import static org.hamcrest.CoreMatchers.is;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
 *
 * @author Michele Zanella <it.polimi.meteoCal>
 */
@RunWith(Arquillian.class)
public class UsersFacadeIT {

    @EJB
    UsersFacade uf;
    @Inject
    private Principal principal;
    @EJB
    private RequestFacade requestFacade;
    @EJB
    private UpdatesFacade updateFacade;
    @EJB
    private BadWeatherNotificationFacade bwnFacade;
    @EJB
    private SuggestionFacade suggestionFacade;
    @EJB
    ResetManager rm;

    @PersistenceContext
    EntityManager em;

    Users newUser1 = new Users();
    Users newUser2 = new Users();
    String sameUsername = "asd";
    String email = "asd@asd.it";
    String password = "asd";
    Date birthDate = Calendar.getInstance().getTime();
    String name = "Name";
    String surname = "Surname";

    public UsersFacadeIT() {
    }

    @Deployment
    public static WebArchive createArchiveAndDeploy() {
        return ShrinkWrap.create(WebArchive.class)
                .addClass(UsersFacade.class)
                .addClass(RequestFacade.class)
                .addClass(UpdatesFacade.class)
                .addClass(BadWeatherNotificationFacade.class)
                .addClass(SuggestionFacade.class)
                .addClass(Principal.class)
                .addClass(ResetManager.class)
                .addPackage(Users.class.getPackage())
                .addAsResource("test-persistence.xml", "META-INF/persistence.xml")
                .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
    }

    @Before
    public void setUp() {
        uf.requestFacade = requestFacade;
        uf.principal = principal;
        uf.bwnFacade = bwnFacade;
        uf.suggestionFacade = suggestionFacade;
        uf.updateFacade = updateFacade;
        uf.em = em;

        newUser1.setEmail(email);
        newUser1.setName(name);
        newUser1.setSurname(surname);
        newUser1.setDateOfBirth(birthDate);
        newUser1.setType("USERS");
        newUser1.setCalendar(new it.polimi.meteoCal.entity.Calendar());
        newUser1.setUsername(sameUsername);
        newUser1.setPassword(password);

        newUser2.setEmail("dif@dif.it");
        newUser2.setName(name);
        newUser2.setSurname(surname);
        newUser2.setDateOfBirth(birthDate);
        newUser2.setType("USERS");
        newUser2.setCalendar(new it.polimi.meteoCal.entity.Calendar());
        newUser2.setUsername(sameUsername);
        newUser2.setPassword(password);

        rm.em = em;
        rm.resetDB();

        uf.create(newUser1);
    }

    @Test
    public void UserManagerShouldBeInjected() {
        assertNotNull(uf);
    }

    @Test
    public void EntityManagerShouldBeInjected() {
        assertNotNull(em);
    }

    @Test
    public void newUsersShouldBeValid() {
        Users newUser = new Users();
        newUser.setUsername(null);
        newUser.setEmail("invalidemail");
        try {
            uf.create(newUser);
        } catch (Exception e) {
            assertTrue(e.getCause() instanceof ConstraintViolationException);
        }
        assertNull(em.find(Users.class, "invalidemail"));
    }

    @Test
    public void passwordsShouldBeEncryptedOnDB() {
        Users foundUser = em.find(Users.class, sameUsername);
        assertNotNull(foundUser);
        assertThat(foundUser.getPassword(), is(PasswordEncrypter.encryptPassword(password)));
    }

    @Test
    public void usernameShouldBeUnique() {
        assertFalse(uf.isUsernameUnique(newUser2.getUsername()));
    }

    @Test
    public void emailShouldBeUnique() {
        assertTrue(uf.isEmailUnique(newUser2.getEmail()));
    }
}
